/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.unifor.ia;

import java.util.Random;
import java.util.Vector;

/**
 * Classe que vai representar o ambiente em forma de matriz.
 * @author pedro
 */
public class Ambiente {   
    /**
     * Matriz bidimensional que vai mapear a tela.
     */
    private int[][] matrix;
    /**
     * Posição do monstro.
     */
    private Posicao wumpusPos;
    /**
     * Posição do ouro.
     */
    private Posicao ouroPos;
    /**
     * Representa se o ouro foi removido do cenário.
     */
    private boolean ouroRemovido;
    /**
     * Vetor para representar os buracos que aparecerão na tela, quantidade de buracos randômica.
     */
    private Vector<Posicao> buracos;
     /**
     * Variável auxiliar para tratar de uma posição.
     */
    private Posicao posAux;
    /**
     * Variável que indica se o monstro foi removido da matriz.
     */
    private boolean wumpusRemovido;

    /**
     * Contrutor
     */
    public Ambiente() {
        matrix = new int[Cenario.WIDTH_CANVAS / Cenario.UNID_AREA][Cenario.HEIGHT_CANVAS / Cenario.UNID_AREA];
        buracos = new Vector<Posicao>();
        popularMatriz();

    }

    public Posicao getWumpusPos() {
        return wumpusPos;
    }

    public void setWumpusPos(Posicao wumpusPos) {
        this.wumpusPos = wumpusPos;
    }
    
    /**
     * Representação do personagem.
     */
    public static final int SIMB_PERSONAGEM = 1;
    /**
     * Representação do monstro.
     */
    public static final int SIMB_WUMPUS = 2;
    /**
     * Representação do fedor do monstro.
     */
    public static final int SIMB_FEDOR_WUMPUS = 3;
    /**
     * Representação do ouro.
     */
    public static final int SIMB_OURO = 4;
    /**
     * Representação do brilho do ouro.
     */
    public static final int SIMB_BRILHO_OURO = 5;
    /**
     * Representação do buraco.
     */
    public static final int SIMB_BURACO = 6;
    /**
     * Representação da brisa vinda do buraco.
     */
    public static final int SIMB_BRISA_BURACO = 7;
    /**
     * Representação da entrada/saída do ambiente.
     */
    public static final int SIMB_ENTRADA_SAIDA = 8;
    /**
     * Representação das posições livres do ambiente.
     */
    public static final int LIVRE = 0;
    /**
     * Método chamado para mover o personagem na matriz.
     * @param ag O agente.
     */

    public void moverPersonagem(Agente ag) {
        posAux = ag.getPos();
        switch (ag.getDirecao()) {
            case Agente.AGENT_DOWN: {
                if (posAux.getY() < 21) {
                    posAux.setY(posAux.getY() + 1);
                }
                break;
            }
            case Agente.AGENT_UP: {
                if (posAux.getY() > 1) {
                    posAux.setY(posAux.getY() - 1);
                }
                break;
            }
            case Agente.AGENT_LEFT: {
                if (posAux.getX() > 2) {
                    posAux.setX(posAux.getX() - 1);
                }
                break;
            }
            case Agente.AGENT_RIGHT: {
                if (posAux.getX() < 29) {
                    posAux.setX(posAux.getX() + 1);
                }
                break;
            }

        }
        ag.setSensor(matrix[posAux.getX()][posAux.getY()]);
        ag.setPos(posAux);
    }
    /**
     * Método que representa a ação de atirar uma flecha para acertar o monstro.
     * @param agent O agente.
     */
    void atirarFlecha(SimpleAgent agent) {
        posAux = agent.getPos();
        if(matrix[posAux.getX()][posAux.getY()]==Ambiente.SIMB_FEDOR_WUMPUS)
        {
            removerObjeto(Ambiente.SIMB_WUMPUS);
        }
        agent.setSoltouFlecha(false);        
    }
    
    /**
     * Método para modificar uma célula da matriz.
     * @param x Posicão x.
     * @param y Posição y.
     * @param what Que objeto vai ser setado na posição indicada pelos parâmetros anteriores.
     */
    private void modificarCelula(int x, int y, int what) {
        matrix[x][y] = what;
    }

    public int[][] getMatrix() {
        return matrix;
    }
    
    /**
     * Método chamado na inicialização que "povoa" a matriz com os objetos do ambiente.
     */
    private void popularMatriz() {
        int randomX, randomY;
        //monstro
        randomX = new Random().nextInt(matrix.length - 5);
        randomY = new Random().nextInt(matrix[0].length - 5);
        if (randomX < 4) {
            randomX = 16;
        }
        if (randomY < 4) {
            randomY = 12;
        }
        //Wumpus
        setWumpusPos(new Posicao(randomX, randomY));
        modificarCelula(getWumpusPos().getX(), getWumpusPos().getY(), Ambiente.SIMB_WUMPUS);
        //fedor
        modificarCelula(getWumpusPos().getX() + 1, getWumpusPos().getY(), Ambiente.SIMB_FEDOR_WUMPUS);
        modificarCelula(getWumpusPos().getX() - 1, getWumpusPos().getY(), Ambiente.SIMB_FEDOR_WUMPUS);
        modificarCelula(getWumpusPos().getX(), getWumpusPos().getY() + 1, Ambiente.SIMB_FEDOR_WUMPUS);
        modificarCelula(getWumpusPos().getX(), getWumpusPos().getY() - 1, Ambiente.SIMB_FEDOR_WUMPUS);
        //ouro
        randomX = new Random().nextInt(matrix.length - 5);
        randomY = new Random().nextInt(matrix[0].length - 5);
        if (randomX < 4) {
            randomX = 12;
        }
        if (randomY < 4) {
            randomY = 16;
        }
        setOuroPos(new Posicao(randomX, randomY));
        modificarCelula(getOuroPos().getX(), getOuroPos().getY(), Ambiente.SIMB_OURO);
        //brilho       
        modificarCelula(getOuroPos().getX() + 1, getOuroPos().getY(), Ambiente.SIMB_BRILHO_OURO);
        modificarCelula(getOuroPos().getX() - 1, getOuroPos().getY(), Ambiente.SIMB_BRILHO_OURO);
        modificarCelula(getOuroPos().getX(), getOuroPos().getY() + 1, Ambiente.SIMB_BRILHO_OURO);
        modificarCelula(getOuroPos().getX(), getOuroPos().getY() - 1, Ambiente.SIMB_BRILHO_OURO);
        //Buracos
        int quantBuracosRandom;
        do
        {
            quantBuracosRandom = new Random().nextInt(8);
        }while(quantBuracosRandom<2);
        if (quantBuracosRandom==0||quantBuracosRandom==1)
            quantBuracosRandom = 2;
        for (int i = 0; i < quantBuracosRandom; i++) {
            randomX = new Random().nextInt(matrix.length - 5);
            randomY = new Random().nextInt(matrix[0].length - 5);
            if (randomX < 4) {
                randomX = 7;
            }
            if (randomY < 4) {
                randomY = 9;
            }
            posAux = new Posicao(randomX, randomY);
            modificarCelula(posAux.getX(), posAux.getY(), Ambiente.SIMB_BURACO);
            //brisa      
            modificarCelula(posAux.getX() + 1, posAux.getY(), Ambiente.SIMB_BRISA_BURACO);
            modificarCelula(posAux.getX() - 1, posAux.getY(), Ambiente.SIMB_BRISA_BURACO);
            modificarCelula(posAux.getX(), posAux.getY() + 1, Ambiente.SIMB_BRISA_BURACO);
            modificarCelula(posAux.getX(), posAux.getY() - 1, Ambiente.SIMB_BRISA_BURACO);
            getBuracos().add(posAux);
        }
        //entrada/saida
        posAux = new Posicao(2, 21);
        modificarCelula(posAux.getX(), posAux.getY(), Ambiente.SIMB_ENTRADA_SAIDA);

    }

    public Posicao getOuroPos() {
        return ouroPos;
    }

    public void setOuroPos(Posicao ouroPos) {
        this.ouroPos = ouroPos;
    }
    
    /**
     * Método chamado para remover algum objeto da matriz.
     * @param objeto Objeto a ser removido.
     */
    public void removerObjeto(int objeto) { 
        posAux = null;
        switch(objeto)
        {
            case Ambiente.SIMB_OURO:
                posAux = getOuroPos();
                ouroRemovido=true;
                break;
            case Ambiente.SIMB_WUMPUS:
                posAux = getWumpusPos();
                setWumpusRemovido(true);
                break;               
        }
        
        modificarCelula(posAux.getX(), posAux.getY(), Ambiente.LIVRE);
              
        modificarCelula(posAux.getX() + 1, posAux.getY(), Ambiente.LIVRE);
        modificarCelula(posAux.getX() - 1, posAux.getY(), Ambiente.LIVRE);
        modificarCelula(posAux.getX(), posAux.getY() + 1, Ambiente.LIVRE);
        modificarCelula(posAux.getX(), posAux.getY() - 1, Ambiente.LIVRE);        
    }

    public boolean isOuroRemovido() {
        return ouroRemovido;
    }

    public void setOuroRemovido(boolean ouroRemovido) {
        this.ouroRemovido = ouroRemovido;
    }

    public Vector<Posicao> getBuracos() {
        return buracos;
    }

    public void setBuracos(Vector<Posicao> buracos) {
        this.buracos = buracos;
    }

    public boolean isWumpusRemovido() {
        return wumpusRemovido;
    }

    public void setWumpusRemovido(boolean wumpusRemovido) {
        this.wumpusRemovido = wumpusRemovido;
    }
}
